using System;
using System.IO;
using System.Collections;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowHider
{
	public class MainForm : System.Windows.Forms.Form
	{
		//Win32 API imports
		[DllImport("user32.dll")] private static extern bool IsWindow(IntPtr hWND);

		//HotKeyFilter object
		private HotKeyFilter HotKeys;
        
		//window obj used to hide the main form
		private Window myself;
		//window obj used to throw up a decoy window on hide all
		private Window coverup;

		private System.Windows.Forms.Label label1;
		private System.Windows.Forms.Button HideButton;
		private System.Windows.Forms.ListBox VisListBox;
		private System.Windows.Forms.Button ShowButton;
		private System.Windows.Forms.CheckBox CoverBox;
		private System.Windows.Forms.Button PickButton;
		private System.Windows.Forms.Button SettingsButton;
		private System.ComponentModel.Container components = null;

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			this.HideButton = new System.Windows.Forms.Button();
			this.label1 = new System.Windows.Forms.Label();
			this.CoverBox = new System.Windows.Forms.CheckBox();
			this.PickButton = new System.Windows.Forms.Button();
			this.VisListBox = new System.Windows.Forms.ListBox();
			this.ShowButton = new System.Windows.Forms.Button();
			this.SettingsButton = new System.Windows.Forms.Button();
			this.SuspendLayout();
			// 
			// HideButton
			// 
			this.HideButton.Anchor = (System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right);
			this.HideButton.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
			this.HideButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.HideButton.Location = new System.Drawing.Point(326, 65);
			this.HideButton.Name = "HideButton";
			this.HideButton.Size = new System.Drawing.Size(85, 23);
			this.HideButton.TabIndex = 2;
			this.HideButton.Text = "Hide";
			this.HideButton.Click += new System.EventHandler(this.btnHide_Click);
			// 
			// label1
			// 
			this.label1.Location = new System.Drawing.Point(8, 7);
			this.label1.Name = "label1";
			this.label1.Size = new System.Drawing.Size(100, 16);
			this.label1.TabIndex = 1;
			this.label1.Text = "Selected Windows:";
			// 
			// CoverBox
			// 
			this.CoverBox.Anchor = (System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left);
			this.CoverBox.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
			this.CoverBox.Location = new System.Drawing.Point(8, 176);
			this.CoverBox.Name = "CoverBox";
			this.CoverBox.Size = new System.Drawing.Size(184, 16);
			this.CoverBox.TabIndex = 5;
			this.CoverBox.Text = "Activate decoy window on hide";
			this.CoverBox.CheckedChanged += new System.EventHandler(this.CoverBox_CheckedChanged);
			// 
			// PickButton
			// 
			this.PickButton.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
			this.PickButton.Location = new System.Drawing.Point(326, 26);
			this.PickButton.Name = "PickButton";
			this.PickButton.Size = new System.Drawing.Size(85, 23);
			this.PickButton.TabIndex = 6;
			this.PickButton.Text = "Pick Windows";
			this.PickButton.Click += new System.EventHandler(this.PickButton_Click);
			// 
			// VisListBox
			// 
			this.VisListBox.Location = new System.Drawing.Point(8, 23);
			this.VisListBox.Name = "VisListBox";
			this.VisListBox.SelectionMode = System.Windows.Forms.SelectionMode.None;
			this.VisListBox.Size = new System.Drawing.Size(311, 147);
			this.VisListBox.TabIndex = 0;
			// 
			// ShowButton
			// 
			this.ShowButton.Anchor = (System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right);
			this.ShowButton.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
			this.ShowButton.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0)));
			this.ShowButton.Location = new System.Drawing.Point(326, 104);
			this.ShowButton.Name = "ShowButton";
			this.ShowButton.Size = new System.Drawing.Size(85, 23);
			this.ShowButton.TabIndex = 4;
			this.ShowButton.Text = "Show";
			this.ShowButton.Click += new System.EventHandler(this.btnShow_Click);
			// 
			// SettingsButton
			// 
			this.SettingsButton.FlatStyle = System.Windows.Forms.FlatStyle.Popup;
			this.SettingsButton.Location = new System.Drawing.Point(326, 143);
			this.SettingsButton.Name = "SettingsButton";
			this.SettingsButton.Size = new System.Drawing.Size(85, 23);
			this.SettingsButton.TabIndex = 7;
			this.SettingsButton.Text = "Settings";
			this.SettingsButton.Click += new System.EventHandler(this.SettingsButton_Click);
			// 
			// MainForm
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(420, 197);
			this.Controls.AddRange(new System.Windows.Forms.Control[] {
																		  this.SettingsButton,
																		  this.PickButton,
																		  this.CoverBox,
																		  this.ShowButton,
																		  this.HideButton,
																		  this.label1,
																		  this.VisListBox});
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
			this.Name = "MainForm";
			this.Opacity = 0.85000002384185791;
			this.ShowInTaskbar = false;
			this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
			this.Text = "Window Hider";
			this.TopMost = true;
			this.Load += new System.EventHandler(this.MainForm_Load);
			this.ResumeLayout(false);

		}
		#endregion

		public MainForm()
		{
			InitializeComponent();
		}

		[STAThread]
		static void Main() 
		{
			Application.Run(new MainForm());
		}

		private void MainForm_Load(object sender, System.EventArgs e)
		{
			myself = new Window("Window Hider",this.Handle,"");

			//show window picking dialog
			PickWindows();

			//load hotkey settings from file
			DeserializeHotKeys();

			//Add a WM_HOTKEY message filter
			Application.AddMessageFilter(HotKeys);

			//subscribe to hotkey events from the message filter
			HotKeys.HotKeyEvent += new HotKeyFilter.HotKeyHandler(OnHotKey);
		}

		//hide button click event
		private void btnHide_Click(object sender, System.EventArgs e)
		{
			//make each selected window invisible
			foreach (Window wnd in VisListBox.Items)
			{
				wnd.Visible = false;
			}
		}

		//show button click event
		private void btnShow_Click(object sender, System.EventArgs e)
		{
			UnhideAll();
		}

		//unhides all windows
		private void UnhideAll()
		{
			foreach (Window wnd in VisListBox.Items)
			{
				wnd.Visible = true;
			}
		}

		/// <summary>
		/// Shows Window Picker dialog and adds all selected windows to the listbox
		/// </summary>
		private void PickWindows()
		{
			this.TopMost = false;

			//show the Window Picker Dialog
			Chooser dlg = new Chooser();
			//if they choose accept...
			if (dlg.ShowDialog() == DialogResult.OK)
			{
				UnhideAll();

				VisListBox.Items.Clear();

				VisListBox.BeginUpdate();
				foreach(Window wnd in dlg.SelectedWindows)
				{
					VisListBox.Items.Add(wnd);
				}
				VisListBox.EndUpdate();
			}

			this.TopMost = true;
		}

		/// <summary>
		/// HotKeyEvent handler
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="WParam">HotKey ID</param>
		private void OnHotKey(object sender, IntPtr WParam)
		{
			switch ((int)WParam)
			{
				case 666:
					myself.Visible = !myself.Visible;
					break;
				case 13:
					ToggleWindows();
					break;
			}
		}

		/// <summary>
		/// Toggle the visibility of all selected windows
		/// </summary>
		private void ToggleWindows()
		{
			bool hiding = false;

			ArrayList arry = new ArrayList(VisListBox.Items);
			foreach(Window wnd in arry)
			{
				//check if the window is still open
				if (IsWindow(wnd.hWnd))
				{
					//if so, toggle visibility
					wnd.Visible = !wnd.Visible;
					if (wnd.Visible == false)
						hiding = true;
				}
				//if not, remove it from the list
				else
					VisListBox.Items.Remove(wnd);
			}

			//if we just hid windows and there is a coverup assigned
			if (hiding == true && coverup != null)
			{
				coverup.Activate();
			}
		}

		private void CoverBox_CheckedChanged(object sender, System.EventArgs e)
		{
			this.TopMost = false;

			if (CoverBox.Checked)
			{
				Chooser dlg = new Chooser();
				dlg.MultiSelect = false;
				if (dlg.ShowDialog() == DialogResult.OK && dlg.SelectedWindow != null)
				{
					coverup = dlg.SelectedWindow;
				}
				else
				{
					CoverBox.Checked = false;
					coverup = null;
				}
			}

			this.TopMost = true;
		}

		private void SerializeHotKeys()
		{
			Serializer.Serialize(HotKeys,"KeyList.osl");
		}

		private void DeserializeHotKeys()
		{
			try
			{
				HotKeys = (HotKeyFilter)Serializer.Deserialize("KeyList.osl");
				HotKeys.Parent = this;
				HotKeys.RestoreKeys(); //reregister the hotkeys
			}
			//if for whatever reason we couldn't deserialize the hotkey file
			catch
			{
				HotKeys = new HotKeyFilter();
				HotKeys.Parent = this;
				
				HotKeys.Add(new HotKey(666,KeyCodes.Modifier.MOD_ALT,KeyCodes.VirtualKey.VK_Z));
				HotKeys.Add(new HotKey(13,KeyCodes.Modifier.MOD_ALT,KeyCodes.VirtualKey.VK_X));
			}
		}

		protected override void Dispose( bool disposing )
		{
			UnhideAll();

			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		private void PickButton_Click(object sender, System.EventArgs e)
		{
			PickWindows();
		}

		private void SettingsButton_Click(object sender, System.EventArgs e)
		{
			this.TopMost = false;

			//show the settings dialog
			Settings dlg = new Settings();
			
			//update controls on settings dialog
			dlg.Opacity = this.Opacity;
			dlg.Modifiers = HotKeys.HotKey(0).Modifiers;
			
			dlg.HideKey = HotKeys.HotKey(0).VirtualKey;
			dlg.ToggleKey = HotKeys.HotKey(1).VirtualKey;

			//if they accept changes
			if (dlg.ShowDialog() == DialogResult.OK)
			{
				//deal with hotkey changes
				HotKeys.ReleaseKeys();
				HotKeys.Add(new HotKey(666,dlg.Modifiers,dlg.HideKey));
				HotKeys.Add(new HotKey(13,dlg.Modifiers,dlg.ToggleKey));
				SerializeHotKeys();
				
				//update opacity
				this.Opacity = dlg.Opacity;
			}

			this.TopMost = true;
		}

	}
}